1 /* 2 * Collie - An asynchronous event-driven network framework using Dlang development 3 * 4 * Copyright (C) 2015-2017 Shanghai Putao Technology Co., Ltd 5 * 6 * Developer: putao's Dlang team 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 module collie.codec.http.server.websocket; 12 13 import std.socket; 14 import std.exception; 15 16 import std.experimental.allocator.gc_allocator; 17 18 import kiss.container.Vector; 19 import kiss.logger; 20 21 import collie.codec.http.httpmessage; 22 import collie.codec.http.errocode; 23 import collie.codec.http.codec.wsframe; 24 import collie.codec.http.headers; 25 import collie.codec.http.httptansaction; 26 import collie.codec.http.codec.httpcodec; 27 import collie.utils.memory; 28 import collie.codec.http.server; 29 30 31 abstract class IWebSocket : RequestHandler 32 { 33 this(){ 34 } 35 36 pragma(inline) 37 final bool ping(ubyte[] data) 38 { 39 return sendFrame(OpCode.OpCodePing,data); 40 } 41 42 pragma(inline) 43 final bool sendText(string text) 44 { 45 return sendFrame(OpCode.OpCodeText,cast(ubyte[])text); 46 } 47 48 pragma(inline) 49 final bool sendBinary(ubyte[] data) 50 { 51 return sendFrame(OpCode.OpCodeBinary,data); 52 } 53 54 pragma(inline) 55 final bool close(ubyte[] data = null) 56 { 57 return sendFrame(OpCode.OpCodeClose,data); 58 } 59 60 pragma(inline,true) 61 final @property Address remoteAdress() 62 { 63 return _addr; 64 } 65 66 void onClose(ubyte[] data); 67 void onText(string frame); 68 void onPong(ubyte[] frame); 69 void onBinary(ubyte[] frame); 70 void onErro(HTTPErrorCode code); 71 protected: 72 final override void onResquest(HTTPMessage headers) nothrow{} 73 final override void onBody(const ubyte[] data) nothrow{} 74 final override void onEOM() nothrow{} 75 final override void requestComplete() nothrow{} 76 final override void onError(HTTPErrorCode code) nothrow { 77 try { 78 if(code != HTTPErrorCode.TIME_OUT) 79 _downstream = null; 80 onErro(code); 81 } catch(Exception) {} 82 } 83 override bool onUpgtade(CodecProtocol protocol,HTTPMessage msg) nothrow{ 84 //_addr = msg.clientAddress(); 85 collectException(msg.clientAddress(),_addr); 86 if(protocol == CodecProtocol.WEBSOCKET) 87 return true; 88 return false; 89 } 90 91 override void onFrame(ref WSFrame wsf) nothrow{ 92 if(wsf.isControlFrame){ 93 switch(wsf.opCode){ 94 case OpCode.OpCodePing: 95 collectException(sendFrame(OpCode.OpCodePong,wsf.data)); 96 break; 97 case OpCode.OpCodePong: 98 collectException(onPong(wsf.data)); 99 break; 100 case OpCode.OpCodeClose: 101 collectException((){sendFrame(OpCode.OpCodeClose,wsf.data); 102 onClose(wsf.data);}()); 103 break; 104 default: 105 break; 106 } 107 } else { 108 if(wsf.parentCode == OpCode.OpCodeText){ 109 collectException((){ 110 _text ~= wsf.data; 111 if(wsf.isFinalFrame){ 112 onText(cast(string)(_text)); 113 _text = null; 114 } 115 }()); 116 } else { 117 collectException((){ 118 _binary ~= wsf.data; 119 if(wsf.isFinalFrame){ 120 onBinary(_binary); 121 _binary = null; 122 } 123 }()); 124 } 125 } 126 } 127 128 bool sendFrame(OpCode code,ubyte[] data) 129 { 130 if(!_downstream) return false; 131 _downstream.sendWsData(code,data); 132 return true; 133 } 134 135 deprecated("Incorrect spelling. Using sendFrame instead.") 136 bool sendFarme(OpCode code,ubyte[] data) 137 { 138 return sendFrame(code, data); 139 } 140 141 package: 142 ubyte[] _text; 143 ubyte[] _binary; 144 Address _addr; 145 }